package com.thornbird.vehiclerecycling.util;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Hashtable;

public class QRCodeUtil {

    public static final int QR_CODE_SIZE = 320;

    public static final String FORMAT_NAME = "png";

    public static byte[] generateQRCode(String content) throws IOException, WriterException {
        Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable<>();
        hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, QR_CODE_SIZE, QR_CODE_SIZE, hintMap);
        bitMatrix = deleteWhiteEdges(bitMatrix);
        int imageWidth = bitMatrix.getWidth();
        int imageHeight = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
        image.createGraphics();
        Graphics2D graphics = (Graphics2D) image.getGraphics();
        image = graphics.getDeviceConfiguration().createCompatibleImage(imageWidth, imageHeight,
                Transparency.TRANSLUCENT);
        graphics.dispose();
        graphics = image.createGraphics();
        graphics.setColor(Color.BLACK);
        for (int i = 0; i < imageWidth; i++) {
            for (int j = 0; j < imageHeight; j++) {
                if (bitMatrix.get(i, j)) {
                    graphics.fillRect(i, j, 1, 1);
                }
            }
        }
        graphics.dispose();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, FORMAT_NAME, outputStream);
        byte[] data = outputStream.toByteArray();
        outputStream.close();
        return data;
    }

    private static BitMatrix deleteWhiteEdges(BitMatrix bitMatrix) {
        int[] rectangle = bitMatrix.getEnclosingRectangle();
        int width = rectangle[2] + 1;
        int height = rectangle[3] + 1;
        BitMatrix result = new BitMatrix(width + 20, height + 20);
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                if (bitMatrix.get(i + rectangle[0], j + rectangle[1])) {
                    result.set(i + 10, j + 10);
                }
            }
        }
        return result;
    }

}
